package com.shkco.xbjcc.service.impl;

import com.shkco.exception.GlobalCustomException;
import com.shkco.exception.GlobalExceptionCode;
import com.shkco.utils.AssertUtil;
import com.shkco.xbjcc.domain.KillActivity;
import com.shkco.xbjcc.domain.KillCourse;
import com.shkco.xbjcc.mapper.KillActivityMapper;
import com.shkco.xbjcc.service.IKillActivityService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.shkco.xbjcc.service.IKillCourseService;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author whale
 * @since 2022-10-20
 */
@Service
public class KillActivityServiceImpl extends ServiceImpl<KillActivityMapper, KillActivity> implements IKillActivityService {

    @Autowired
    private IKillCourseService killCourseService;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;


    @Override
    @Transactional
    public void release(Long id) {
        // 判断活动是否存在
        KillActivity killActivity = selectById(id);
        AssertUtil.isNotNull(killActivity, GlobalExceptionCode.KILL_ACTIVITY_INEXISTENCE);
        // 判断活动状态
        boolean boo = killActivity.getPublishStatus() == KillActivity.TO_BE_RELEASED;
        AssertUtil.isTrue(boo,GlobalExceptionCode.KILL_ACTIVITY_PUBLISH);
        // 判断秒杀活动开始时间是否在当前时间之后
        Date date = new Date();
        boolean after = killActivity.getBeginTime().after(date);
        AssertUtil.isTrue(after,GlobalExceptionCode.KILL_ACTIVITY_PUBLISH_BEFOR);
        // 根据活动id获取秒杀活动下的所有秒杀课程
        List<KillCourse> killCourses = killCourseService.selectByActivityId(id);
        if (killCourses == null || killCourses.size() <= 0){
            throw new GlobalCustomException(GlobalExceptionCode.KILL_ACTIVITY_NOT_COURSE);
        }
        killCourses.forEach(killCourse -> {
            // 设置信号量
            RSemaphore semaphore = redissonClient.getSemaphore(id + ":" + killCourse.getId());
            boolean isSetPermits = semaphore.trySetPermits(killCourse.getKillCount());
            if (isSetPermits){
                redisTemplate.opsForHash().put(
                        "activity:" + id,
                        killCourse.getId().toString(),
                        killCourse
                );
                killCourse.setPublishStatus(KillActivity.PUBLISHED);
                killCourse.setPublishTime(date);
                killCourseService.updateById(killCourse);
            }
        });
        killActivity.setPublishStatus(KillActivity.PUBLISHED);
        killActivity.setPublishTime(date);
        updateById(killActivity);
    }

    @Override
    public void cancelRelease(Long id) {
        // 判断活动是否存在
        KillActivity killActivity = selectById(id);
        AssertUtil.isNotNull(killActivity, GlobalExceptionCode.KILL_ACTIVITY_INEXISTENCE);
        // 判断活动状态
        boolean boo = killActivity.getPublishStatus() == KillActivity.PUBLISHED;
        AssertUtil.isTrue(boo,GlobalExceptionCode.ERROR);
        // 判断秒杀活动开始时间是否在当前时间之前
        Date date = new Date();
        boolean after = killActivity.getEndTime().after(date);
        AssertUtil.isTrue(after,GlobalExceptionCode.ERROR);
        // 根据活动id获取秒杀活动下的所有秒杀课程
        List<KillCourse> killCourses = killCourseService.selectByActivityId(id);
        killCourses.forEach(killCourse -> {
            redisTemplate.opsForHash().delete("activity:" + id,
                    killCourse.getId().toString());
            killCourse.setPublishStatus(KillActivity.CANCELLED);
            killCourseService.updateById(killCourse);
        });
        killActivity.setPublishStatus(KillActivity.CANCELLED);
        updateById(killActivity);
    }
}
